2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 //==============================================================================
28 This file contains all the gubbins to create an ActiveX browser plugin that
29 wraps your BrowserPluginComponent object.
32 //==============================================================================
35 //==============================================================================
41 #pragma warning (disable:4584)
43 #include "juce_IncludeBrowserPluginInfo.h"
44 #include "../../../juce_amalgamated.h"
45 #include "juce_BrowserPluginComponent.h"
47 #ifndef JuceBrowserPlugin_ActiveXCLSID
48 #error "For an activeX plugin, you need to define JuceBrowserPlugin_ActiveXCLSID in your BrowserPluginCharacteristics.h file!"
51 //==============================================================================
53 static int numDOWID
= 0, numJuceSO
= 0;
58 // Cunning trick used to add functions to export list without messing about with .def files.
59 #define EXPORTED_FUNCTION comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
61 //==============================================================================
62 static void juceVarToVariant (const var
& v
, VARIANT
& dest
);
63 static const var
variantTojuceVar (const VARIANT
& v
);
65 //==============================================================================
66 // Takes care of the logic in invoking var methods from IDispatch callbacks.
73 const String
getStringFromDISPID (const DISPID hash
) const
75 for (int i
= identifierPool
.size(); --i
>= 0;)
76 if (getHashFromString (identifierPool
[i
]) == hash
)
77 return identifierPool
[i
];
82 HRESULT
doGetIDsOfNames (LPOLESTR
* rgszNames
, UINT cNames
, DISPID
* rgDispId
)
84 for (unsigned int i
= 0; i
< cNames
; ++i
)
85 rgDispId
[i
] = getHashFromString (identifierPool
.getPooledString (String (rgszNames
[i
])));
90 HRESULT
doInvoke (const var
& v
,
91 DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
* pDispParams
,
92 VARIANT
* pVarResult
, EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
94 const Identifier
memberId (getStringFromDISPID (dispIdMember
));
96 DynamicObject
* const object
= v
.getDynamicObject();
98 if (memberId
.toString().isEmpty() || object
== nullptr)
99 return DISP_E_MEMBERNOTFOUND
;
101 if ((wFlags
& DISPATCH_METHOD
) != 0)
103 if (! object
->hasMethod (memberId
))
104 return DISP_E_MEMBERNOTFOUND
;
106 const int numArgs
= pDispParams
== nullptr ? 0 : pDispParams
->cArgs
;
111 result
= v
.call (memberId
);
116 for (int j
= numArgs
; --j
>= 0;)
117 args
.add (variantTojuceVar (pDispParams
->rgvarg
[j
]));
119 result
= v
.invoke (memberId
, numArgs
== 0 ? 0 : args
.getRawDataPointer(), numArgs
);
122 if (pVarResult
!= nullptr)
123 juceVarToVariant (result
, *pVarResult
);
127 else if ((wFlags
& DISPATCH_PROPERTYGET
) != 0)
129 if (! object
->hasProperty (memberId
))
130 return DISP_E_MEMBERNOTFOUND
;
132 if (pVarResult
!= nullptr)
134 juceVarToVariant (object
->getProperty (memberId
), *pVarResult
);
138 else if ((wFlags
& DISPATCH_PROPERTYPUT
) != 0)
140 if (pDispParams
!= nullptr && pDispParams
->cArgs
> 0)
142 object
->setProperty (memberId
, variantTojuceVar (pDispParams
->rgvarg
[0]));
147 return DISP_E_MEMBERNOTFOUND
;
151 StringPool identifierPool
;
153 static DISPID
getHashFromString (const String::CharPointerType
& s
) noexcept
155 return (DISPID
) (pointer_sized_int
) s
.getAddress();
158 IDispatchHelper (const IDispatchHelper
&);
159 IDispatchHelper
& operator= (const IDispatchHelper
&);
162 //==============================================================================
163 // Makes a var look like an IDispatch
164 class IDispatchWrappingDynamicObject
: public IDispatch
167 IDispatchWrappingDynamicObject (const var
& object_
)
171 DBG ("num Juce wrapper objs: " + String (++numJuceSO
));
174 virtual ~IDispatchWrappingDynamicObject()
176 DBG ("num Juce wrapper objs: " + String (--numJuceSO
));
179 HRESULT __stdcall
QueryInterface (REFIID id
, void __RPC_FAR
* __RPC_FAR
* result
)
181 if (id
== IID_IUnknown
) { AddRef(); *result
= (IUnknown
*) this; return S_OK
; }
182 else if (id
== IID_IDispatch
) { AddRef(); *result
= (IDispatch
*) this; return S_OK
; }
185 return E_NOINTERFACE
;
188 ULONG __stdcall
AddRef() { return ++refCount
; }
189 ULONG __stdcall
Release() { const int r
= --refCount
; if (r
== 0) delete this; return r
; }
191 HRESULT __stdcall
GetTypeInfoCount (UINT
*) { return E_NOTIMPL
; }
192 HRESULT __stdcall
GetTypeInfo (UINT
, LCID
, ITypeInfo
**) { return E_NOTIMPL
; }
194 HRESULT __stdcall
GetIDsOfNames (REFIID riid
, LPOLESTR
* rgszNames
, UINT cNames
,
195 LCID lcid
, DISPID
* rgDispId
)
197 return iDispatchHelper
.doGetIDsOfNames (rgszNames
, cNames
, rgDispId
);
200 HRESULT __stdcall
Invoke (DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
,
201 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
202 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
204 return iDispatchHelper
.doInvoke (object
, dispIdMember
, riid
, lcid
, wFlags
, pDispParams
,
205 pVarResult
, pExcepInfo
, puArgErr
);
209 //==============================================================================
212 IDispatchHelper iDispatchHelper
;
216 //==============================================================================
217 // Makes an IDispatch look like a var
218 class DynamicObjectWrappingIDispatch
: public DynamicObject
220 IDispatch
* const source
;
223 DynamicObjectWrappingIDispatch (IDispatch
* const source_
)
227 log ("num IDispatch wrapper objs: " + String (++numDOWID
));
230 ~DynamicObjectWrappingIDispatch()
233 log ("num IDispatch wrapper objs: " + String (--numDOWID
));
236 var
getProperty (const Identifier
& propertyName
) const
238 const String
nameCopy (propertyName
.toString());
239 LPCOLESTR name
= nameCopy
.toUTF16();
241 if (source
->GetIDsOfNames (IID_NULL
, (LPOLESTR
*) &name
, 1, 0, &id
) == S_OK
)
250 if (source
->Invoke (id
, IID_NULL
, 0, DISPATCH_PROPERTYGET
,
251 ¶ms
, &result
, &excepInfo
, &argError
) == S_OK
)
253 var
v (variantTojuceVar (result
));
254 VariantClear (&result
);
262 bool hasProperty (const Identifier
& propertyName
) const
264 const String
nameCopy (propertyName
.toString());
265 LPCOLESTR name
= nameCopy
.toUTF16();
267 return source
->GetIDsOfNames (IID_NULL
, (LPOLESTR
*) &name
, 1, 0, &id
) == S_OK
;
270 void setProperty (const Identifier
& propertyName
, const var
& newValue
)
272 const String
nameCopy (propertyName
.toString());
273 LPCOLESTR name
= nameCopy
.toUTF16();
275 if (source
->GetIDsOfNames (IID_NULL
, (LPOLESTR
*) &name
, 1, 0, &id
) == S_OK
)
279 juceVarToVariant (newValue
, param
);
281 DISPPARAMS dispParams
;
282 zerostruct (dispParams
);
283 dispParams
.cArgs
= 1;
284 dispParams
.rgvarg
= ¶m
;
286 zerostruct (excepInfo
);
292 if (source
->Invoke (id
, IID_NULL
, 0, DISPATCH_PROPERTYPUT
,
293 &dispParams
, &result
, &excepInfo
, &argError
) == S_OK
)
295 VariantClear (&result
);
298 VariantClear (¶m
);
302 void removeProperty (const Identifier
& propertyName
)
304 setProperty (propertyName
, var::null
);
307 bool hasMethod (const Identifier
& methodName
) const
309 const String
nameCopy (methodName
.toString());
310 LPCOLESTR name
= nameCopy
.toUTF16();
312 return source
->GetIDsOfNames (IID_NULL
, (LPOLESTR
*) &name
, 1, 0, &id
) == S_OK
;
315 var
invokeMethod (const Identifier
& methodName
, const var
* parameters
, int numParameters
)
318 const String
nameCopy (methodName
.toString());
319 LPCOLESTR name
= nameCopy
.toUTF16();
321 if (source
->GetIDsOfNames (IID_NULL
, (LPOLESTR
*) &name
, 1, 0, &id
) == S_OK
)
323 HeapBlock
<VARIANT
> params
;
324 params
.calloc (numParameters
+ 1);
326 for (int i
= 0; i
< numParameters
; ++i
)
327 juceVarToVariant (parameters
[(numParameters
- 1) - i
], params
[i
]);
329 DISPPARAMS dispParams
;
330 zerostruct (dispParams
);
331 dispParams
.cArgs
= numParameters
;
332 dispParams
.rgvarg
= params
;
335 zerostruct (excepInfo
);
341 if (source
->Invoke (id
, IID_NULL
, 0, DISPATCH_METHOD
,
342 &dispParams
, &result
, &excepInfo
, &argError
) == S_OK
)
344 returnValue
= variantTojuceVar (result
);
345 VariantClear (&result
);
354 //==============================================================================
355 void juceVarToVariant (const var
& v
, VARIANT
& dest
)
364 dest
.intVal
= (int) v
;
369 dest
.boolVal
= (int) v
;
371 else if (v
.isDouble())
374 dest
.dblVal
= (double) v
;
376 else if (v
.isString())
379 dest
.bstrVal
= SysAllocString (v
.toString().toUTF16());
381 else if (v
.getDynamicObject() != nullptr)
383 dest
.vt
= VT_DISPATCH
;
384 dest
.pdispVal
= new IDispatchWrappingDynamicObject (v
);
386 else if (v
.isMethod())
392 const var
variantTojuceVar (const VARIANT
& v
)
394 if ((v
.vt
& VT_ARRAY
) != 0)
400 switch (v
.vt
& ~VT_BYREF
)
403 case VT_EMPTY
: return var::null
;
404 case VT_I1
: return var ((int) v
.cVal
);
405 case VT_I2
: return var ((int) v
.iVal
);
406 case VT_I4
: return var ((int) v
.lVal
);
407 case VT_I8
: return var (String (v
.llVal
));
408 case VT_UI1
: return var ((int) v
.bVal
);
409 case VT_UI2
: return var ((int) v
.uiVal
);
410 case VT_UI4
: return var ((int) v
.ulVal
);
411 case VT_UI8
: return var (String (v
.ullVal
));
412 case VT_INT
: return var ((int) v
.intVal
);
413 case VT_UINT
: return var ((int) v
.uintVal
);
414 case VT_R4
: return var ((double) v
.fltVal
);
415 case VT_R8
: return var ((double) v
.dblVal
);
416 case VT_BSTR
: return var (String (v
.bstrVal
));
417 case VT_BOOL
: return var (v
.boolVal
? true : false);
418 case VT_DISPATCH
: return var (new DynamicObjectWrappingIDispatch (v
.pdispVal
));
427 //==============================================================================
428 // This acts as the embedded HWND
429 class AXBrowserPluginHolderComponent
: public Component
432 //==============================================================================
433 AXBrowserPluginHolderComponent()
438 setWantsKeyboardFocus (false);
440 addAndMakeVisible (child
= createBrowserPlugin());
441 jassert (child
!= nullptr); // You have to create one of these!
444 ~AXBrowserPluginHolderComponent()
450 //==============================================================================
451 void paint (Graphics
& g
)
453 if (child
== nullptr || ! child
->isOpaque())
454 g
.fillAll (Colours::white
);
459 if (child
!= nullptr)
460 child
->setBounds (0, 0, getWidth(), getHeight());
463 const var
getObject() { return child
->getJavascriptObject(); }
465 void setWindow (IOleInPlaceSite
* site
)
467 if (browser
!= nullptr)
477 site
->GetWindow (&newHWND
);
479 IServiceProvider
* sp
= nullptr;
480 site
->QueryInterface (IID_IServiceProvider
, (void**) &sp
);
484 sp
->QueryService (IID_IWebBrowserApp
, IID_IWebBrowser2
, (void**) &browser
);
489 if (parentHWND
!= newHWND
)
494 parentHWND
= newHWND
;
500 HWND ourHWND
= (HWND
) getWindowHandle();
501 SetParent (ourHWND
, parentHWND
);
502 DWORD val
= GetWindowLong (ourHWND
, GWL_STYLE
);
503 val
= (val
& ~WS_POPUP
) | WS_CHILD
;
504 SetWindowLong (ourHWND
, GWL_STYLE
, val
);
511 site
->OnInPlaceActivate();
514 const String
getBrowserURL() const
516 if (browser
== nullptr)
517 return String::empty
;
520 browser
->get_LocationURL (&url
);
521 return URL::removeEscapeChars (url
);
525 //==============================================================================
526 ScopedPointer
<BrowserPluginComponent
> child
;
528 IWebBrowser2
* browser
;
531 //==============================================================================
532 extern String browserVersionDesc
;
534 static const String
getExePath()
536 TCHAR moduleFile
[2048] = { 0 };
537 GetModuleFileName (0, moduleFile
, 2048);
541 static const String
getExeVersion (const String
& exeFileName
, const String
& fieldName
)
544 DWORD pointlessWin32Variable
;
545 DWORD size
= GetFileVersionInfoSize (exeFileName
.toUTF16(), &pointlessWin32Variable
);
549 HeapBlock
<char> exeInfo
;
550 exeInfo
.calloc (size
);
552 if (GetFileVersionInfo (exeFileName
.toUTF16(), 0, size
, exeInfo
))
554 TCHAR
* result
= nullptr;
555 unsigned int resultLen
= 0;
557 // try the 1200 codepage (Unicode)
558 String
queryStr ("\\StringFileInfo\\040904B0\\" + fieldName
);
560 if (! VerQueryValue (exeInfo
, (LPTSTR
) queryStr
.toUTF16().getAddress(), (void**) &result
, &resultLen
))
562 // try the 1252 codepage (Windows Multilingual)
563 queryStr
= "\\StringFileInfo\\040904E4\\" + fieldName
;
564 VerQueryValue (exeInfo
, (LPTSTR
) queryStr
.toUTF16().getAddress(), (void**) &result
, &resultLen
);
567 resultString
= String (result
, resultLen
);
574 static int numActivePlugins
= 0;
576 class JuceActiveXObject
: public IUnknown
,
578 public IObjectWithSite
,
579 public IObjectSafety
,
580 public IOleInPlaceObject
584 : site (nullptr), refCount (0)
586 log ("JuceActiveXObject");
591 log ("~JuceActiveXObject");
592 holderComp
= nullptr;
595 HRESULT __stdcall
QueryInterface (REFIID id
, void __RPC_FAR
* __RPC_FAR
* result
)
597 if (id
== IID_IUnknown
) { AddRef(); *result
= (IUnknown
*) this; return S_OK
; }
598 else if (id
== IID_IDispatch
) { AddRef(); *result
= (IDispatch
*) this; return S_OK
; }
599 else if (id
== IID_IObjectWithSite
) { AddRef(); *result
= (IObjectWithSite
*) this; return S_OK
; }
600 else if (id
== IID_IObjectSafety
) { AddRef(); *result
= (IObjectSafety
*) this; return S_OK
; }
601 else if (id
== IID_IOleInPlaceObject
) { AddRef(); *result
= (IOleInPlaceObject
*) this; return S_OK
; }
602 else if (id
== IID_IOleWindow
) { AddRef(); *result
= (IOleWindow
*) (IOleInPlaceObject
*) this; return S_OK
; }
605 return E_NOINTERFACE
;
608 ULONG __stdcall
AddRef() { return ++refCount
; }
609 ULONG __stdcall
Release() { const int r
= --refCount
; if (r
== 0) delete this; return r
; }
611 HRESULT __stdcall
GetTypeInfoCount (UINT
* pctinfo
) { return E_NOTIMPL
; }
612 HRESULT __stdcall
GetTypeInfo (UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
) { return E_NOTIMPL
; }
614 HRESULT __stdcall
GetIDsOfNames (REFIID riid
, LPOLESTR
* rgszNames
, UINT cNames
,
615 LCID lcid
, DISPID
* rgDispId
)
617 return iDispatchHelper
.doGetIDsOfNames (rgszNames
, cNames
, rgDispId
);
620 HRESULT __stdcall
Invoke (DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
,
621 DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
622 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
624 if (holderComp
== nullptr)
625 return DISP_E_MEMBERNOTFOUND
;
627 return iDispatchHelper
.doInvoke (holderComp
->getObject(),
628 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
,
629 pVarResult
, pExcepInfo
, puArgErr
);
632 HRESULT __stdcall
SetSite (IUnknown
* newSite
)
645 IOleInPlaceSite
* inPlaceSite
= nullptr;
646 site
->QueryInterface (IID_IOleInPlaceSite
, (void**) &inPlaceSite
);
648 if (inPlaceSite
!= nullptr)
652 holderComp
->setWindow (inPlaceSite
);
653 inPlaceSite
->Release();
669 void createHolderComp()
671 if (holderComp
== nullptr)
673 if (numActivePlugins
++ == 0)
675 log ("initialiseJuce_GUI()");
676 initialiseJuce_GUI();
678 browserVersionDesc
= "Internet Explorer " + getExeVersion (getExePath(), "FileVersion");
681 holderComp
= new AXBrowserPluginHolderComponent();
685 void deleteHolderComp()
687 if (holderComp
!= nullptr)
689 holderComp
= nullptr;
691 if (--numActivePlugins
== 0)
693 log ("shutdownJuce_GUI()");
699 HRESULT __stdcall
GetSite (REFIID riid
, void **ppvSite
)
705 //==============================================================================
706 HRESULT __stdcall
SetObjectRects (LPCRECT r
, LPCRECT c
)
708 if (holderComp
!= nullptr)
709 holderComp
->setBounds (r
->left
, r
->top
, r
->right
- r
->left
, r
->bottom
- r
->top
);
714 HRESULT __stdcall
GetWindow (HWND
* phwnd
)
716 if (holderComp
== nullptr)
719 *phwnd
= (HWND
) holderComp
->getWindowHandle();
723 //==============================================================================
724 HRESULT __stdcall
ContextSensitiveHelp (BOOL fEnterMode
) { return E_NOTIMPL
; }
725 HRESULT __stdcall
InPlaceDeactivate() { return E_NOTIMPL
; }
726 HRESULT __stdcall
UIDeactivate() { return E_NOTIMPL
; }
727 HRESULT __stdcall
ReactivateAndUndo() { return E_NOTIMPL
; }
729 //==============================================================================
730 HRESULT __stdcall
GetInterfaceSafetyOptions (REFIID riid
, DWORD
*pdwSupportedOptions
, DWORD
*pdwEnabledOptions
)
732 *pdwSupportedOptions
= *pdwEnabledOptions
= INTERFACESAFE_FOR_UNTRUSTED_CALLER
|INTERFACESAFE_FOR_UNTRUSTED_DATA
;
736 HRESULT __stdcall
SetInterfaceSafetyOptions (REFIID
, DWORD
, DWORD
) { return S_OK
; }
741 ScopedPointer
<AXBrowserPluginHolderComponent
> holderComp
;
742 IDispatchHelper iDispatchHelper
;
744 JuceActiveXObject (const JuceActiveXObject
&);
745 JuceActiveXObject
& operator= (const JuceActiveXObject
&);
748 //==============================================================================
749 class JuceActiveXObjectFactory
: public IUnknown
,
753 JuceActiveXObjectFactory() : refCount (0) {}
754 ~JuceActiveXObjectFactory() {}
756 HRESULT __stdcall
QueryInterface (REFIID id
, void __RPC_FAR
* __RPC_FAR
* result
)
758 if (id
== IID_IUnknown
) { AddRef(); *result
= (IUnknown
*) this; return S_OK
; }
759 else if (id
== IID_IClassFactory
) { AddRef(); *result
= (IClassFactory
*) this; return S_OK
; }
762 return E_NOINTERFACE
;
765 ULONG __stdcall
AddRef() { return ++refCount
; }
766 ULONG __stdcall
Release() { const int r
= --refCount
; if (r
== 0) delete this; return r
; }
768 HRESULT __stdcall
CreateInstance (IUnknown
* pUnkOuter
, REFIID riid
, void** ppvObject
)
770 *ppvObject
= nullptr;
772 if (pUnkOuter
!= nullptr && riid
!= IID_IUnknown
)
773 return CLASS_E_NOAGGREGATION
;
775 JuceActiveXObject
* ax
= new JuceActiveXObject();
776 return ax
->QueryInterface (riid
, ppvObject
);
779 HRESULT __stdcall
LockServer (BOOL
/*fLock*/) { return S_OK
; }
784 JuceActiveXObjectFactory (const JuceActiveXObjectFactory
&);
785 JuceActiveXObjectFactory
& operator= (const JuceActiveXObjectFactory
&);
788 //==============================================================================
789 const String
getActiveXBrowserURL (const BrowserPluginComponent
* comp
)
791 AXBrowserPluginHolderComponent
* const ax
= dynamic_cast <AXBrowserPluginHolderComponent
*> (comp
->getParentComponent());
792 return ax
!= nullptr ? ax
->getBrowserURL() : String::empty
;
795 //==============================================================================
796 extern "C" BOOL WINAPI
DllMain (HANDLE instance
, DWORD reason
, LPVOID
)
798 #pragma EXPORTED_FUNCTION
802 case DLL_PROCESS_ATTACH
:
803 log ("DLL_PROCESS_ATTACH");
804 PlatformUtilities::setCurrentModuleInstanceHandle (instance
);
807 case DLL_PROCESS_DETACH
:
808 log ("DLL_PROCESS_DETACH");
809 browserVersionDesc
= String::empty
;
811 // IE has a tendency to leak our objects, so although none of this should be
812 // necessary, it's best to make sure..
813 jassert (numActivePlugins
== 0);
824 static const String
CLSIDToJuceString (REFCLSID clsid
)
827 StringFromIID (clsid
, &s
);
830 return String::empty
;
832 const String
result (s
);
834 CoGetMalloc (1, &malloc
);
835 if (malloc
!= nullptr)
841 return result
.removeCharacters ("{}").trim();
844 STDAPI
DllGetClassObject (REFCLSID rclsid
, REFIID riid
, LPVOID
* ppv
)
846 #pragma EXPORTED_FUNCTION
850 if (CLSIDToJuceString (rclsid
).equalsIgnoreCase (String (JuceBrowserPlugin_ActiveXCLSID
)))
852 JuceActiveXObjectFactory
* afx
= new JuceActiveXObjectFactory();
853 if (afx
->QueryInterface (riid
, ppv
) == S_OK
)
859 return CLASS_E_CLASSNOTAVAILABLE
;
862 STDAPI
DllCanUnloadNow()
864 #pragma EXPORTED_FUNCTION
868 //==============================================================================
869 static const String
makeLegalRegistryName (const String
& s
)
871 return s
.retainCharacters ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.");
874 static HRESULT
doRegistration (const bool unregister
)
876 const String
company (makeLegalRegistryName (JuceBrowserPlugin_Company
));
877 const String
plugin (makeLegalRegistryName (JuceBrowserPlugin_Name
));
878 const String
clsID ("{" + String (JuceBrowserPlugin_ActiveXCLSID
).toUpperCase() + "}");
879 const String
root ("HKEY_CLASSES_ROOT\\");
880 const String
companyDotPlugin (company
+ "." + plugin
);
881 const String
companyDotPluginCur (companyDotPlugin
+ ".1");
882 const String
clsIDRoot (root
+ "CLSID\\" + clsID
+ "\\");
883 const String
dllPath (File::getSpecialLocation (File::currentApplicationFile
).getFullPathName());
885 StringPairArray settings
;
886 settings
.set (root
+ companyDotPluginCur
+ "\\", JuceBrowserPlugin_Name
);
887 settings
.set (root
+ companyDotPluginCur
+ "\\CLSID\\", clsID
);
888 settings
.set (root
+ companyDotPlugin
+ "\\", JuceBrowserPlugin_Name
);
889 settings
.set (root
+ companyDotPlugin
+ "\\CLSID\\", clsID
);
890 settings
.set (root
+ companyDotPlugin
+ "\\CurVer\\", companyDotPluginCur
);
891 settings
.set (clsIDRoot
, JuceBrowserPlugin_Name
);
892 settings
.set (clsIDRoot
+ "Implemented Categories\\{7DD95801-9882-11CF-9FA9-00AA006C42C4}\\", String::empty
);
893 settings
.set (clsIDRoot
+ "Implemented Categories\\{7DD95802-9882-11CF-9FA9-00AA006C42C4}\\", String::empty
);
894 settings
.set (clsIDRoot
+ "ProgID\\", companyDotPluginCur
);
895 settings
.set (clsIDRoot
+ "VersionIndependentProgID\\", companyDotPlugin
);
896 settings
.set (clsIDRoot
+ "Programmable\\", String::empty
);
897 settings
.set (clsIDRoot
+ "InProcServer32\\", dllPath
);
898 settings
.set (clsIDRoot
+ "InProcServer32\\ThreadingModel", "Apartment");
899 settings
.set (clsIDRoot
+ "Control\\", String::empty
);
900 settings
.set (clsIDRoot
+ "Insertable\\", String::empty
);
901 settings
.set (clsIDRoot
+ "ToolboxBitmap32\\", dllPath
+ ", 101");
902 settings
.set (clsIDRoot
+ "TypeLib\\", "");
903 settings
.set (clsIDRoot
+ "Version\\", JuceBrowserPlugin_Version
);
907 for (int i
= 0; i
< settings
.getAllKeys().size(); ++i
)
908 PlatformUtilities::deleteRegistryValue (settings
.getAllKeys()[i
]);
910 PlatformUtilities::deleteRegistryKey (root
+ companyDotPluginCur
);
911 PlatformUtilities::deleteRegistryKey (root
+ companyDotPlugin
);
912 PlatformUtilities::deleteRegistryKey (clsIDRoot
);
914 if (PlatformUtilities::registryValueExists (clsIDRoot
+ "InProcServer32"))
915 return SELFREG_E_CLASS
;
919 PlatformUtilities::deleteRegistryKey (clsIDRoot
);
921 for (int i
= 0; i
< settings
.getAllKeys().size(); ++i
)
922 PlatformUtilities::setRegistryValue (settings
.getAllKeys()[i
],
923 settings
[settings
.getAllKeys()[i
]]);
925 // check whether the registration actually worked - if not, we probably don't have
926 // enough privileges to write to the registry..
927 if (PlatformUtilities::getRegistryValue (clsIDRoot
+ "InProcServer32\\") != dllPath
)
928 return SELFREG_E_CLASS
;
934 STDAPI
DllRegisterServer()
936 #pragma EXPORTED_FUNCTION
937 return doRegistration (false);
940 STDAPI
DllUnregisterServer()
942 #pragma EXPORTED_FUNCTION
943 return doRegistration (true);